package atguigu.springcloud.controller;

import atguigu.springcloud.lb.LoadBalancer;
import com.atguigu.springcloud.common.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.baomidou.mybatisplus.extension.api.R;
import com.my.feign.ITestFeign;
import com.my.feign.ITestFeignBackFactory;
import com.my.feign.ITestFeignNoFallBack;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;

/**
 * @auther zzyy
 * @create 2020-02-18 17:23
 */
@RestController
@Slf4j
//需要和方法上的@HystrixCommand()配合使用
//@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderController{


    //    public static final String PAYMENT_URL = "http://localhost:8001";
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    /*支持负载均衡  restTemplate+Ribbon 这里用的netflix-eureka-client自带了ribbon  （ApplicationContextConfig） */
    @Resource
    private RestTemplate restTemplate;
    /*自定义负载均衡算法*/
    @Resource
    private LoadBalancer loadBalancer;
    /*openfeign远程调用*/
//    @Autowired
    @Resource
    private ITestFeign iTestFeign;
    @Resource
    private ITestFeignBackFactory backFactory;
    @Resource
    private ITestFeignNoFallBack noFallBack;

    @Resource
    private DiscoveryClient discoveryClient;
    /*restTemplate 的使用 以下三个方法 ↓*/
    /*基础服务调用*/
    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL +"/payment/create",payment, CommonResult.class);
    }

    /*返回json*/
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id, CommonResult.class);
    }
    /*返回对象*/
    @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id, CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }else{
            return new CommonResult<>(444,"操作失败");
        }
    }
    /*restTemplate 的使用 ↑*/

    /*自定义负载均衡*/
    @GetMapping(value = "/consumer/payment/lb")
    public String getPaymentLB(){
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if(instances == null || instances.size() <= 0){
            return null;
        }
        ServiceInstance serviceInstance = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb", String.class);
    }
    /*openFeign*/
    @GetMapping("testOpenFeing")
//    @HystrixCommand //配合DefaultProperties使用 可以做成全局
    @HystrixCommand(
        fallbackMethod = "payment_Global_FallbackMethod"
    )
    public R<Payment> testOpenFeing(){
        return iTestFeign.findOne(1L);
    }
    @GetMapping("testOpenFeing2")
    public R<Payment> testOpenFeing2(){
        return iTestFeign.findOne(1L);
    }

    //下面是hystrix全局fallback方法
    public R<Payment> payment_Global_FallbackMethod(){
        return R.failed("异常处理信息，111请稍后再试，o(╥﹏╥)o");
    }
    /*使用工厂降级*/
    @GetMapping("testOpenFeing/backFactory")
    public R<Payment> testOpenFeingbackFactory(){
        return backFactory.findOne(1L);
    }
    /*使用全局自定义默认降级*/
    @GetMapping("testOpenFeing/noBack")
    public R<Payment> testOpenFeingnoFallBack(){
        return noFallBack.findOne(1L);
    }
    /*延时返回*/
    @GetMapping("timeOut")
    @HystrixCommand(
            fallbackMethod = "payment_Global_FallbackMethod",
            commandProperties = {
                    //超时时间
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3200")
            }
    )
    public R timeOut(){
        return iTestFeign.timeOut();
    }

    @GetMapping("timeOut2")
    public R timeOut2(){
        return backFactory.timeOut();
    }

    @GetMapping("timeOut3")
    public R timeOut3(){
        return noFallBack.timeOut();
    }


    // ====================> zipkin+sleuth
    @GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin()
    {
        String result = restTemplate.getForObject("http://localhost:8001"+"/payment/zipkin/", String.class);
        return result;
    }
}
